// *****************************************************************************
//
// Copyright (c) 2019, Southwest Research Institute® (SwRI®)
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//     * Redistributions of source code must retain the above copyright
//       notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above copyright
//       notice, this list of conditions and the following disclaimer in the
//       documentation and/or other materials provided with the distribution.
//     * Neither the name of Southwest Research Institute® (SwRI®) nor the
//       names of its contributors may be used to endorse or promote products
//       derived from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL Southwest Research Institute® BE LIABLE 
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
// DAMAGE.
//
// *****************************************************************************

#ifndef MAPVIZ_PLUGINS_FLOAT_PLUGIN_H
#define MAPVIZ_PLUGINS_FLOAT_PLUGIN_H

#include <string>

#include <mapviz/mapviz_plugin.h>

#include <QObject>
#include <QString>
#include <QColor>
#include <QWidget>
#include <QGLWidget>
#include <QPainter>
#include <QFont>
#include <QStaticText>

#include <rclcpp/rclcpp.hpp>

#include <std_msgs/msg/float32.hpp>
#include <std_msgs/msg/float64.hpp>
#include <marti_common_msgs/msg/float32_stamped.hpp>
#include <marti_common_msgs/msg/float64_stamped.hpp>
#include <marti_sensor_msgs/msg/velocity.hpp>

// QT autogenerated files
#include "ui_float_config.h"

namespace mapviz_plugins
{
  class FloatPlugin : public mapviz::MapvizPlugin
  {
    Q_OBJECT

  public:
    enum Anchor {
      TOP_LEFT,
      TOP_CENTER,
      TOP_RIGHT,
      CENTER_LEFT,
      CENTER,
      CENTER_RIGHT,
      BOTTOM_LEFT,
      BOTTOM_CENTER,
      BOTTOM_RIGHT
    };

    enum Units {
      PIXELS,
      PERCENT
    };

    FloatPlugin();
    ~FloatPlugin() override = default;

    bool Initialize(QGLWidget* canvas) override;
    void Shutdown() override {}

    void Draw(double x, double y, double scale) override;
    void Paint(QPainter* painter, double x, double y, double scale) override;

    void Transform() override {}

    void LoadConfig(const YAML::Node& node, const std::string& path) override;
    void SaveConfig(YAML::Emitter& emitter, const std::string& path) override;

    QWidget* GetConfigWidget(QWidget* parent) override;

    bool SupportsPainting() override
    {
      return true;
    }

  protected:
    void PaintText(QPainter* painter);
    void PrintError(const std::string& message) override;
    void PrintInfo(const std::string& message) override;
    void PrintWarning(const std::string& message) override;

  protected Q_SLOTS:
    void SelectColor();
    void SelectFont();
    void SelectTopic();
    void TopicEdited();
    void SetAnchor(QString anchor);
    void SetUnits(QString units);
    void SetOffsetX(int offset);
    void SetOffsetY(int offset);
    void PostfixEdited();

  private:
    Ui::float_config ui_;
    QWidget* config_widget_;

    std::string topic_;
    rmw_qos_profile_t qos_;
    std::string postfix_;
    Anchor anchor_;
    Units units_;
    int offset_x_;
    int offset_y_;

    rclcpp::Subscription<std_msgs::msg::Float32>::SharedPtr float32_sub_;
    rclcpp::Subscription<std_msgs::msg::Float64>::SharedPtr float64_sub_;
    rclcpp::Subscription<marti_common_msgs::msg::Float32Stamped>::SharedPtr float32_stamped_sub_;
    rclcpp::Subscription<marti_common_msgs::msg::Float64Stamped>::SharedPtr float64_stamped_sub_;
    rclcpp::Subscription<marti_sensor_msgs::msg::Velocity>::SharedPtr velocity_sub_;
    bool has_message_;
    bool has_painted_;

    QColor color_;
    QFont font_;
    QStaticText message_;

    void floatCallback(double value);
    void connectCallback(const std::string& topic, const rmw_qos_profile_t& qos);

    std::string AnchorToString(Anchor anchor);
    std::string UnitsToString(Units units);

    static const char* ANCHOR_KEY;
    static const char* COLOR_KEY;
    static const char* FONT_KEY;
    static const char* OFFSET_X_KEY;
    static const char* OFFSET_Y_KEY;
    static const char* TOPIC_KEY;
    static const char* UNITS_KEY;
    static const char* POSTFIX_KEY;
  };
}


#endif //MAPVIZ_PLUGINS_FLOAT_PLUGIN_H
